package com.luoran.bartalks.service.impl;

import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toCollection;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.luoran.bartalks.action.vo.CompanyTemplateData;
import com.luoran.bartalks.action.vo.TreeDataRepair;
import com.luoran.bartalks.core.UserContext;
import com.luoran.bartalks.dao.IBtCodingRuleDao;
import com.luoran.bartalks.dao.IBtContainerTemplateDao;
import com.luoran.bartalks.dao.IBtPlanTemplateDao;
import com.luoran.bartalks.dao.IBtPlanTemplateEntryDao;
import com.luoran.bartalks.dao.IBtPositionDao;
import com.luoran.bartalks.dao.IBtRegionDao;
import com.luoran.bartalks.dao.IBtTransoprtModeDao;
import com.luoran.bartalks.entity.biz.BtCodingRule;
import com.luoran.bartalks.entity.biz.BtContainerTemplate;
import com.luoran.bartalks.entity.biz.BtPlanTemplate;
import com.luoran.bartalks.entity.biz.BtPlanTemplateEntry;
import com.luoran.bartalks.entity.biz.BtPosition;
import com.luoran.bartalks.entity.biz.BtRegion;
import com.luoran.bartalks.entity.biz.BtTransportMode;
import com.luoran.bartalks.service.IBtInitBasicInfoService;
import com.luoran.bartalks.utils.UUID;

@Service
@Transactional(rollbackFor = Exception.class)
public class BtInitBasicInfoService implements IBtInitBasicInfoService {

	@Autowired
	private IBtCodingRuleDao codingRuleDao;

	@Autowired
	private IBtContainerTemplateDao containerTemplateDao;

	@Autowired
	private IBtTransoprtModeDao transoprtModeDao;

	@Autowired
	private IBtPositionDao positionDao;

	@Autowired
	private IBtRegionDao regionDao;

	@Autowired
	private IBtPlanTemplateDao planTemplateDao;

	@Autowired
	private IBtPlanTemplateEntryDao planTemplateEntryDao;

	@Override
	public void initBasicInfo(List<BtCodingRule> codingRules, List<BtContainerTemplate> templates,
			List<BtTransportMode> transportModes, List<BtRegion> regions, String companyId) {
		// 初始化各种单据类型的编码生成规则+容器模板
		try {
			// 先删除该公司所有的编码规则
			codingRuleDao.deleteRulesByCompanyId(companyId);
			// 再添加新规则
			codingRuleDao.insertBatch(codingRules);
			// 删除容器模板
			containerTemplateDao.deleteTemplatesByCompanyId(companyId);
			// 添加新容器模板
			containerTemplateDao.insertBatch(templates);
			// 删除运输方式
			transoprtModeDao.deleteTransportModesByCompanyId(companyId);
			// 添加运输方式
			transoprtModeDao.insertBatch(transportModes);
			// 删除位置
			positionDao.deletePositionByCompanyId(companyId);
			// 删除区域
			regionDao.deleteRegionByCompanyId(companyId);
			// 添加区域
			regionDao.insertBatch(regions);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public JSONObject StencilCompanyDataImput(CompanyTemplateData companyTemplateData, String StencilCompanyId) {
		Date now = new Date();
		String userId = UserContext.get().getId();
		JSONObject result = new JSONObject();
		// 公司数据校验
		List<String> company = companyTemplateData.getCompany();
		if (company != null && company.size() == 0) {
			result.put("state", false);
			result.put("msg", "传入数据错误,无目标公司信息!");
			return result;
		}

		for (String companyId : company) {
			List<BtCodingRule> codingRules = new ArrayList<BtCodingRule>();
			List<BtContainerTemplate> containerTemplates = new ArrayList<BtContainerTemplate>();
			List<BtPlanTemplate> planTemplates = new ArrayList<BtPlanTemplate>();
			List<BtPlanTemplateEntry> planTemplateEntrys = new ArrayList<BtPlanTemplateEntry>();
			List<BtRegion> regions = new ArrayList<BtRegion>();
			List<BtPosition> positions = new ArrayList<BtPosition>();
			List<BtTransportMode> transportModes = new ArrayList<BtTransportMode>();
			// 编码规则
			if (companyTemplateData.getCodeRule().size() > 0) {
				codingRules = codingRuleDao.getByIds(companyTemplateData.getCodeRule());
				for (BtCodingRule btCodingRule : codingRules) {
					// 查询当前类型的编码规则在待导入的公司中是否存在并且开启
					List<BtCodingRule> dataList = codingRuleDao.getcodingRuleStencilList(companyId);
					if (dataList == null) {
						btCodingRule.setRuleStatus(0);
					} else {
						List<BtCodingRule> listfilter = dataList.stream()
								.filter(d -> d.getBillType().equals(btCodingRule.getBillType()))
								.collect(Collectors.toList());
						// 编码规则的状态.0启用,1停用
						if (listfilter == null) {
							btCodingRule.setRuleStatus(0);
						} else {
							btCodingRule.setRuleStatus(1);
						}
					}
					btCodingRule.setCodingSuffix("-MB" + UUID.get());
					btCodingRule.setCompanyId(companyId);
					btCodingRule.setCreateTime(now);
				}
			}
			// 容器模板
			if (companyTemplateData.getContainer().size() > 0) {
				containerTemplates = containerTemplateDao.getByIds(companyTemplateData.getContainer());
				for (BtContainerTemplate btContainerTemplate : containerTemplates) {
					btContainerTemplate.setCompanyId(companyId);
					btContainerTemplate.setCreatTime(now);
					btContainerTemplate.setTemplateCode("MB-RQMB-" + UUID.get());
					btContainerTemplate.setFounder(userId);
				}
			}
			// 运输方式
			if (companyTemplateData.getTransport().size() > 0) {
				transportModes.addAll(transoprtModeDao.getByIds(companyTemplateData.getTransport()));
			}
			if (companyTemplateData.getPostion().size() > 0) {
				positions.addAll(positionDao.getByIds(companyTemplateData.getPostion()));
			}
			if (companyTemplateData.getRegion().size() > 0) {
				regions.addAll(regionDao.getByCodes(companyTemplateData.getRegion(), StencilCompanyId));
			}

			List<BtTransportMode> transportModesInPlanTemplate = new ArrayList<BtTransportMode>();
			List<BtPosition> positionInPlanTemplate = new ArrayList<BtPosition>();
			List<BtRegion> regionInPlanTemplate = new ArrayList<BtRegion>();
			// 计划中包含运输方式,地点,区域 ,途经点信息等,将信息获取存入list
			if (companyTemplateData.getPlan().size() > 0) {
				planTemplates = planTemplateDao.getByIds(companyTemplateData.getPlan());
				for (BtPlanTemplate planTemplate : planTemplates) {
					// 运输方式信息
					BtTransportMode transportMode = transoprtModeDao.single(planTemplate.getTransportTypeId());
					if (transportMode != null) {
						transportModesInPlanTemplate.add(transportMode);
					} else {
						result.put("state", false);
						result.put("msg", "数据错误,无" + planTemplate.getTransportTypeId() + "该运输方式信息!");
						return result;
					}
					// 途经点信息
					List<BtPlanTemplateEntry> btPlanTemplateEntryByParentId = planTemplateEntryDao
							.getBtPlanTemplateEntryByParentId(planTemplate.getId(), StencilCompanyId);
					planTemplateEntrys.addAll(btPlanTemplateEntryByParentId);
					for (BtPlanTemplateEntry btPlanTemplateEntry : btPlanTemplateEntryByParentId) {
						BtPosition position = positionDao.single(btPlanTemplateEntry.getPositionId());
						if (position != null) {
							// 获得位置
							positionInPlanTemplate.add(position);
							// 根据位置找区域
							BtRegion regionByRegCode = regionDao.getRegionByRegCode(position.getParentRegPositionCode(),
									StencilCompanyId);
							if (regionByRegCode != null) {
								// 区域父级寻找,并且加入list
								try {
									regionInPlanTemplate.addAll(findFatherNode(regionInPlanTemplate, regionByRegCode));
									List<BtRegion> regionsUnique = regionInPlanTemplate.stream()
											.collect(collectingAndThen(
													toCollection(
															() -> new TreeSet<>(Comparator.comparing(BtRegion::getId))),
													ArrayList::new));
									regionInPlanTemplate = regionsUnique;
								} catch (Exception e) {
									result.put("state", false);
									result.put("msg", e.getMessage());
									return result;
								}
							} else {
								result.put("state", false);
								result.put("msg", "数据错误,无" + position.getParentRegPositionCode() + "该区域信息!");
								return result;
							}

						} else {
							result.put("state", false);
							result.put("msg", "数据错误,无" + btPlanTemplateEntry.getPositionId() + "该位置信息!");
							return result;
						}
					}

				}
			}
			// 添加信息进总list
			transportModes.addAll(transportModesInPlanTemplate);
			positions.addAll(positionInPlanTemplate);
			regions.addAll(regionInPlanTemplate);

			// 根据id去重
			List<BtTransportMode> transportModesUnique = transportModes.stream().collect(collectingAndThen(
					toCollection(() -> new TreeSet<>(Comparator.comparing(BtTransportMode::getId))), ArrayList::new));
			transportModes = transportModesUnique;
			for (BtTransportMode btTransportMode : transportModes) {
				btTransportMode.setCompanyId(companyId);
				btTransportMode.setFounder(userId);
				btTransportMode.setCreateTime(now);
			}
			List<BtPosition> positionsUnique = positions.stream().collect(collectingAndThen(
					toCollection(() -> new TreeSet<>(Comparator.comparing(BtPosition::getId))), ArrayList::new));
			positions = positionsUnique;
			List<BtRegion> regionsUnique = regions.stream().collect(collectingAndThen(
					toCollection(() -> new TreeSet<>(Comparator.comparing(BtRegion::getId))), ArrayList::new));
			regions = regionsUnique;
			if (planTemplates == null || planTemplates.size() == 0) {
				for (BtTransportMode btTransportMode : transportModes) {
					String transportId = UUID.get();
					String transportCode = UUID.get();
					btTransportMode.setId(transportId);
					btTransportMode.setTransportCode("MB-YSFS-" + transportCode);
				}
			} else {
				// 循环计划模板,将运输方式与途经点的code,id 修改
				for (BtPlanTemplate btPlanTemplate : planTemplates) {
					String planTemplateId = UUID.get();
					String planTemplateCode = UUID.get();
					// 运输方式
					for (BtTransportMode btTransportMode : transportModes) {
						String transportId = UUID.get();
						String transportCode = UUID.get();
						if (btPlanTemplate.getTransportTypeId().equals(btTransportMode.getId())) {
							btPlanTemplate.setTransportTypeId(transportId);
							btPlanTemplate.setTransportCode("MB-YSFS-" + transportCode);
						}
						btTransportMode.setId(transportId);
						btTransportMode.setTransportCode("MB-YSFS-" + transportCode);
					}
					// 途经点
					for (BtPlanTemplateEntry btPlanTemplateEntry : planTemplateEntrys) {
						String planTemplateEntryId = UUID.get();
						if (btPlanTemplate.getId().equals(btPlanTemplateEntry.getPlanTemplateId())) {
							btPlanTemplateEntry.setPlanTemplateId(planTemplateId);
							btPlanTemplate.setId(planTemplateId);
						}
						btPlanTemplateEntry.setId(planTemplateEntryId);
						btPlanTemplateEntry.setCompanyId(companyId);
						btPlanTemplateEntry.setCreateTime(now);
						btPlanTemplateEntry.setFounder(userId);
					}
					btPlanTemplate.setCompanyId(companyId);
					btPlanTemplate.setPlanTemplateCode("MB-JHMB-" + planTemplateCode);
					btPlanTemplate.setCreateTime(now);
					btPlanTemplate.setFounder(userId);
				}
			}
			// list转换为树结构操作类
			Map<String, Object> regionMap = new HashMap<String, Object>();
			for (BtRegion btRegion : regions) {
				btRegion.setCompanyId(companyId);
				btRegion.setCreateTime(now);
				btRegion.setFounder(userId);
				TreeDataRepair treeDataRepair = new TreeDataRepair();
				BtRegion data = new BtRegion();
				BeanUtils.copyProperties(btRegion, data);
				treeDataRepair.setRegion(data);
				treeDataRepair.setId(btRegion.getId());
				treeDataRepair.setParentId(btRegion.getParentRegId());
				treeDataRepair.setParentCode(btRegion.getParentRegCode());
				treeDataRepair.setCode(btRegion.getRegionCode());
				treeDataRepair.setLongCode(btRegion.getLongCode());
				regionMap.put(treeDataRepair.getId(), treeDataRepair);
			}
			for (BtPosition btPosition : positions) {
				btPosition.setCompanyId(companyId);
				btPosition.setCreateTime(now);
				btPosition.setFounder(userId);
			}
			for (BtRegion btRegion : regions) {
				if (btRegion.getParentRegId() == null || ("").equals(btRegion.getParentRegId())) {
					String regionId = UUID.get();
					String regionCode = UUID.get();
					TreeDataRepair treeDataRepair = (TreeDataRepair) regionMap.get(btRegion.getId());
					treeDataRepair.getRegion().setId(regionId);
					treeDataRepair.getRegion().setParentRegId(null);
					treeDataRepair.getRegion().setParentRegCode(null);
					treeDataRepair.getRegion().setRegionCode("MB-QY-" + regionCode);
					treeDataRepair.getRegion().setLongCode("MB-QY-" + regionCode);
					// 找对应的子位置
					for (BtPosition btPosition : positions) {
						if (btPosition.getParentRegPositionCode().equals(treeDataRepair.getCode())) {
							String positionId = UUID.get();
							String positionCode = UUID.get();
							// 位置子集中该改对应的计划模板起始地目的地
							for (BtPlanTemplate btPlanTemplate : planTemplates) {
								if (btPlanTemplate.getDestinationId().equals(btPosition.getId())) {
									btPlanTemplate.setDestinationId(positionId);
									btPlanTemplate.setDestinationCode("MB-WZ-" + positionCode);
								}
								if (btPlanTemplate.getStartPlaceId().equals(btPosition.getId())) {
									btPlanTemplate.setStartPlaceId(positionId);
									btPlanTemplate.setStartPlaceCode("MB-WZ-" + positionCode);
								}
							}
							// 位置子集中该改对应的途经点
							for (BtPlanTemplateEntry btPlanTemplateEntry : planTemplateEntrys) {
								if (btPlanTemplateEntry.getPositionId().equals(btPosition.getId())) {
									btPlanTemplateEntry.setPositionId(positionId);
									btPlanTemplateEntry.setPositionCode("MB-WZ-" + positionCode);
								}
							}
							btPosition.setId(positionId);
							btPosition.setPositionCode("MB-WZ-" + positionCode);
							btPosition.setLongCode("MB-QY-" + regionCode + "!MB-WZ-" + positionCode);
							btPosition.setParentRegPositionCode("MB-QY-" + regionCode);
						}
					}
					// 找对应的子区域
					List<BtRegion> regionFilter = regions.stream()
							.filter(regionByList -> treeDataRepair.getId().equals(regionByList.getParentRegId()))
							.collect(Collectors.toList());
					if (regionFilter.size() != 0) {
						regionMap = findChlidNode(regionMap, regionFilter, regions, positions, planTemplateEntrys,
								planTemplates, btRegion);
					}
				}
			}
			regions.clear();
			for (Object obj : regionMap.values()) {
				TreeDataRepair treeDataRepair = new TreeDataRepair();
				treeDataRepair = (TreeDataRepair) obj;
				regions.add(treeDataRepair.getRegion());
			}
			/*
			 * System.out.println(JSONObject.toJSONString(regions));
			 * System.out.println(JSONObject.toJSONString(positions));
			 * System.out.println(JSONObject.toJSONString(planTemplates));
			 * System.out.println(JSONObject.toJSONString(transportModes));
			 * System.out.println(JSONObject.toJSONString(planTemplateEntrys));
			 */
			try {
				codingRuleDao.insertBatch(codingRules);
				containerTemplateDao.insertBatch(containerTemplates);
				regionDao.insertBatch(regions);
				positionDao.insertBatch(positions);
				transoprtModeDao.insertBatch(transportModes);
				planTemplateDao.insertBatch(planTemplates);
				planTemplateEntryDao.insertBatch(planTemplateEntrys);
			} catch (Exception e) {
				e.printStackTrace();
				result.put("state", false);
				result.put("msg", "系统错误，请联系管理员！");
				return result;
			}
		}
		result.put("state", true);
		return result;
	}

	/**
	 * 通过递归迭代方法寻找区子区域并修改数据
	 */
	public Map<String, Object> findChlidNode(Map<String, Object> regionMap, List<BtRegion> regionChild,
			List<BtRegion> regions, List<BtPosition> positions, List<BtPlanTemplateEntry> planTemplateEntrys,
			List<BtPlanTemplate> planTemplates, BtRegion region) {
		for (BtRegion btRegion : regionChild) {
			String regionId = UUID.get();
			String regionCode = UUID.get();
			TreeDataRepair treeDataRepairFather = (TreeDataRepair) regionMap.get(region.getId());
			TreeDataRepair treeDataRepairChlid = (TreeDataRepair) regionMap.get(btRegion.getId());
			treeDataRepairChlid.getRegion().setId(regionId);
			treeDataRepairChlid.getRegion().setParentRegId(treeDataRepairFather.getRegion().getId());
			treeDataRepairChlid.getRegion().setParentRegCode(treeDataRepairFather.getRegion().getRegionCode());
			treeDataRepairChlid.getRegion().setRegionCode("MB-QY-" + regionCode);
			treeDataRepairChlid.getRegion()
					.setLongCode(treeDataRepairFather.getRegion().getLongCode() + "!MB-QY-" + regionCode);
			// 找对应的子位置
			for (BtPosition btPosition : positions) {
				if (btPosition.getParentRegPositionCode().equals(treeDataRepairChlid.getCode())) {
					String positionId = UUID.get();
					String positionCode = UUID.get();
					// 位置子集中该改对应的计划模板起始地目的地
					for (BtPlanTemplate btPlanTemplate : planTemplates) {
						if (btPlanTemplate.getDestinationId().equals(btPosition.getId())) {
							btPlanTemplate.setDestinationId(positionId);
							btPlanTemplate.setDestinationCode("MB-WZ-" + positionCode);
						}
						if (btPlanTemplate.getStartPlaceId().equals(btPosition.getId())) {
							btPlanTemplate.setStartPlaceId(positionId);
							btPlanTemplate.setStartPlaceCode("MB-WZ-" + positionCode);
						}
					}
					// 位置子集中该改对应的途经点
					for (BtPlanTemplateEntry btPlanTemplateEntry : planTemplateEntrys) {
						if (btPlanTemplateEntry.getPositionId().equals(btPosition.getId())) {
							btPlanTemplateEntry.setPositionId(positionId);
							btPlanTemplateEntry.setPositionCode("MB-WZ-" + positionCode);
						}
					}
					btPosition.setId(positionId);
					btPosition.setPositionCode("MB-WZ-" + positionCode);
					btPosition.setLongCode(treeDataRepairChlid.getRegion().getLongCode() + "!MB-WZ-" + positionCode);
					btPosition.setParentRegPositionCode("MB-QY-" + regionCode);
				}
			}
			List<BtRegion> regionFilter = regions.stream()
					.filter(regionByList -> btRegion.getId().equals(regionByList.getParentRegId()))
					.collect(Collectors.toList());
			if (regionFilter.size() != 0) {
				regionMap = findChlidNode(regionMap, regionFilter, regions, positions, planTemplateEntrys,
						planTemplates, btRegion);
			}
		}
		return regionMap;
	}

	/**
	 * 通过递归方法寻找区域父级数据 ,返回list
	 * 
	 * @param list
	 * @param region
	 * @return list
	 * @throws Exception
	 */
	public List<BtRegion> findFatherNode(List<BtRegion> regionList, BtRegion region) throws Exception {
		regionList.add(region);
		if (region.getParentRegId() == null || "".equals(region.getParentRegId())) {
			// 没有父级
			return regionList;
		} else {
			// 有父级
			BtRegion regionById = regionDao.single(region.getParentRegId());
			if (regionById == null) {
				throw new Exception("数据错误,无" + region.getParentRegId() + "该区域信息");
			}
			findFatherNode(regionList, regionById);
		}
		return regionList;
	}

}
